﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Org.BouncyCastle.Asn1;

namespace TheClerk.Forms.Templates.raw.Envelope
{
    #region public Postmark
    /// <summary>
    /// Timestamp over EnvelopeContent
    /// </summary>
    /// <remarks>
    /// Postmark ::= TimeStampToken
    /// </remarks>
    public class Postmark : TimeStamp
    {
        private string digestName;
        private System.IO.Stream streamToPostmark;

        public Postmark(string s, System.IO.Stream streamToPostmark)
        {
            // TODO: Complete member initialization
            this.digestName = s;
            this.streamToPostmark = streamToPostmark;
        }

        public System.IO.Stream Serialize()
        {
            // TODO NotImplemented
            streamToPostmark.Position = 0;

            // Get the digest

            var DigestObject = Org.BouncyCastle.Security.DigestUtilities.GetDigest(digestName);

            var toPostmark = new byte[streamToPostmark.Length];
            streamToPostmark.Read(toPostmark, 0, toPostmark.Length);
            DigestObject.BlockUpdate(toPostmark, 0, toPostmark.Length);
            var actualDigest = new byte[DigestObject.GetDigestSize()];
            DigestObject.DoFinal(actualDigest, 0);

            var tsrg = new Org.BouncyCastle.Tsp.TimeStampRequestGenerator();
            var tsreq = tsrg.Generate(Org.BouncyCastle.Security.DigestUtilities.GetObjectIdentifier(digestName), actualDigest);

            // Now, we submit it for timestamping

            //string[] rfc3161serviceURLs = new string[] {
            //    "http://www.startssl.com/timestamp",
            //    "http://timestamp.comodoca.com/rfc3161"
            //};

            var rfc3161serviceURL = "http://timestamp.comodoca.com/rfc3161";
            var webRequest = System.Net.WebRequest.Create(rfc3161serviceURL) as System.Net.HttpWebRequest;

            webRequest.Accept = "application/timestamp-reply";
            webRequest.AllowWriteStreamBuffering = true;
            webRequest.ContentType = "application/timestamp-query";
            webRequest.Method = "POST";
            webRequest.AllowAutoRedirect = false;
            webRequest.AutomaticDecompression = System.Net.DecompressionMethods.None;
            webRequest.Pipelined = false;
            webRequest.SendChunked = false;
            webRequest.UserAgent = "TheClerk/0.0.1";

            var webRequestPayload = tsreq.GetEncoded();
            // webRequest.ContentLength = d.Length;
            var requestStream = webRequest.GetRequestStream();
            requestStream.Write(webRequestPayload, 0, (int)webRequestPayload.Length);

            // Here is where we get the response
            var e = webRequest.GetResponse();
            //if (e.ContentType != "application/timestamp-reply")
            //    throw new IOException("cannot comprehend the response for the timestamp request");
            var f = e.GetResponseStream();
            MemoryStream h = new MemoryStream();
            f.CopyTo(h);
            h.Position = 0;
            var g = new byte[h.Length];
            h.Read(g, 0, g.Length);
            // let's explore this response a bit
            var response = new Org.BouncyCastle.Tsp.TimeStampResponse(g);
            if (response.Status != 0)
            {
                Instrumentation.nullTSPresponses++;
                Instrumentation.TSPresponsecodes.Add(response.Status);
                return null;
            }
            var token = response.TimeStampToken;

            // just for now
            //System.Diagnostics.Debugger.Break();
            var ms = new System.IO.MemoryStream(token.GetEncoded());
            ms.Position = 0;
            return ms;
        }


        public byte[] AsByteArray()
        {
            System.IO.Stream myinput = Serialize();
            byte[] buf = new byte[myinput.Length];
            myinput.Read(buf, 0, buf.Length);
            return buf;
        }

        // TODO: Make this into a functional timestamp
        public Asn1Encodable toAsn1Encodable()
        {
            var mytemp = Serialize();
            if (mytemp == null)
                return null;
            return Org.BouncyCastle.Asn1.Asn1Object.FromStream(mytemp);
        }
    }
    #endregion
}
